home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / ddj0492.zip / DFLT11.ZIP / DIALBOX.C < prev    next >
Text File  |  1992-01-27  |  22KB  |  918 lines

  1. /* ----------------- dialbox.c -------------- */
  2.  
  3. #include "dflat.h"
  4.  
  5. static char path[MAXPATH];
  6. static char drive[MAXDRIVE] = " :";
  7. static char dir[MAXDIR];
  8. static char name[MAXFILE];
  9. static char ext[MAXEXT];
  10.  
  11. static int inFocusCommand(DBOX *);
  12. static void dbShortcutKeys(DBOX *, int);
  13. static int ControlProc(WINDOW, MESSAGE, PARAM, PARAM);
  14. static void ChangeFocus(WINDOW, int);
  15. static CTLWINDOW *AssociatedControl(DBOX *, enum commands);
  16. static void SetRadioButton(DBOX *, CTLWINDOW *);
  17.  
  18. static BOOL SysMenuOpen;
  19.  
  20. static DBOX **dbs = NULL;
  21. static int dbct = 0;
  22.  
  23. void ClearDialogBoxes(void)
  24. {
  25.     int i;
  26.     for (i = 0; i < dbct; i++)    {
  27.         CTLWINDOW *ct = (*(dbs+i))->ctl;
  28.         while (ct->class)    {
  29.             if ((ct->class == EDITBOX || ct->class == COMBOBOX) &&
  30.                     ct->itext != NULL)
  31.                 free(ct->itext);
  32.             ct++;
  33.         }
  34.     }
  35.     if (dbs != NULL)    {
  36.         free(dbs);
  37.         dbs = NULL;
  38.     }
  39.     dbct = 0;
  40. }
  41.  
  42. int DialogProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  43. {
  44.     DBOX *db = wnd->extension;
  45.     CTLWINDOW *ct;
  46.     WINDOW cwnd;
  47.     int rtn, i;
  48.  
  49.     switch (msg)    {
  50.         case CREATE_WINDOW:
  51.             /* ---- build a table of processed dialog boxes ---- */
  52.             for (i = 0; i < dbct; i++)
  53.                 if (db == dbs[i])
  54.                     break;
  55.             if (i == dbct)    {
  56.                 dbs = realloc(dbs, sizeof(DBOX *) * (dbct+1));
  57.                 if (dbs != NULL)
  58.                     *(dbs + dbct++) = db;
  59.             }
  60.             rtn = BaseWndProc(DIALOG, wnd, msg, p1, p2);
  61.             ct = db->ctl;
  62.             while (ct->class)    {
  63.                 int attrib = 0;
  64.                 if (TestAttribute(wnd, NOCLIP))
  65.                     attrib |= NOCLIP;
  66.                 if (wnd->Modal)
  67.                     attrib |= SAVESELF;
  68.                 ct->setting = ct->isetting;
  69.                 if (ct->class == EDITBOX && ct->dwnd.h > 1)
  70.                     attrib |= (MULTILINE | HASBORDER);
  71.                 else if (ct->class == LISTBOX || ct->class == TEXTBOX)
  72.                     attrib |= HASBORDER;
  73.                 cwnd = CreateWindow(ct->class,
  74.                              ct->dwnd.title,
  75.                              ct->dwnd.x+GetClientLeft(wnd),
  76.                              ct->dwnd.y+GetClientTop(wnd),
  77.                              ct->dwnd.h,
  78.                              ct->dwnd.w,
  79.                              ct,
  80.                              wnd,
  81.                              ControlProc,
  82.                              attrib);
  83.                 if ((ct->class == EDITBOX ||
  84.                         ct->class == COMBOBOX) &&
  85.                             ct->itext != NULL)
  86.                     SendMessage(cwnd, SETTEXT, (PARAM) ct->itext, 0);
  87.                 if (ct->class != BOX &&
  88.                     ct->class != TEXT &&
  89.                         wnd->dFocus == NULL)
  90.                     wnd->dFocus = ct;
  91.                 ct++;
  92.             }
  93.             return rtn;
  94.         case SETFOCUS:
  95.             if (wnd->Modal)    {
  96.                 if (p1)
  97.                     SendMessage(inFocus, SETFOCUS, FALSE, 0);
  98.                 inFocus = p1 ? wnd : NULL;
  99.                 return TRUE;
  100.             }
  101.             break;
  102.         case SHIFT_CHANGED:
  103.             if (wnd->Modal)
  104.                 return TRUE;
  105.             break;
  106.         case LEFT_BUTTON:
  107.             if (WindowSizing || WindowMoving)
  108.                 return FALSE;
  109.             if (HitControlBox(wnd, p1-GetLeft(wnd), p2-GetTop(wnd)))    {
  110.                 PostMessage(wnd, KEYBOARD, ' ', ALTKEY);
  111.                 return TRUE;
  112.             }
  113.             ct = db->ctl;
  114.             while (ct->class)    {
  115.                 WINDOW cwnd = ct->wnd;
  116.                 if (ct->class == COMBOBOX)    {
  117.                     if (p2 == GetTop(cwnd))    {
  118.                         if (p1 == GetRight(cwnd)+1)    {
  119.                             SendMessage(cwnd, msg, p1, p2);
  120.                             return TRUE;
  121.                         }
  122.                     }
  123.                     if (GetClass(inFocus) == LISTBOX)
  124.                         SendMessage(wnd, SETFOCUS, TRUE, 0);
  125.                 }
  126.                 else if (ct->class == SPINBUTTON)    {
  127.                     if (p2 == GetTop(cwnd))    {
  128.                         if (p1 == GetRight(cwnd)+1 ||
  129.                                 p1 == GetRight(cwnd)+2)    {
  130.                             SendMessage(cwnd, msg, p1, p2);
  131.                             return TRUE;
  132.                         }
  133.                     }
  134.                 }
  135.                 ct++;
  136.             }
  137.             break;
  138.         case KEYBOARD:
  139.             if (WindowMoving || WindowSizing)
  140.                 break;
  141.             switch ((int)p1)    {
  142.                 case F1:
  143.                     ct = wnd->dFocus;
  144.                     if (ct != NULL)
  145.                         if (DisplayHelp(wnd, ct->help))
  146.                             return TRUE;
  147.                     break;
  148.                 case SHIFT_HT:
  149.                 case BS:
  150.                 case UP:
  151.                     ChangeFocus(wnd, FALSE);
  152.                     break;
  153.                 case ALT_F6:
  154.                 case '\t':
  155.                 case FWD:
  156.                 case DN:
  157.                     ChangeFocus(wnd, TRUE);
  158.                     break;
  159.                 case ' ':
  160.                     if (((int)p2 & ALTKEY) && TestAttribute(wnd, CONTROLBOX))    {
  161.                         SysMenuOpen = TRUE;
  162.                         BuildSystemMenu(wnd);
  163.                     }
  164.                     break;
  165.                 case CTRL_F4:
  166.                 case ESC:
  167.                     SendMessage(wnd, COMMAND, ID_CANCEL, 0);
  168.                     break;
  169.                 default:
  170.                     /* ------ search all the shortcut keys ----- */
  171.                     dbShortcutKeys(db, (int) p1);
  172.                     break;
  173.             }
  174.             if (wnd->Modal)
  175.                 return TRUE;
  176.             break;
  177.         case CLOSE_POPDOWN:
  178.             SysMenuOpen = FALSE;
  179.             break;
  180.         case LB_SELECTION:
  181.         case LB_CHOOSE:
  182.             if (SysMenuOpen)
  183.                 return TRUE;
  184.             SendMessage(wnd, COMMAND, inFocusCommand(db), msg);
  185.             break;
  186.         case COMMAND:
  187.             switch ((int) p1)    {
  188.                 case ID_OK:
  189.                 case ID_CANCEL:
  190.                     if ((int)p2 != 0)
  191.                         return TRUE;
  192.                     wnd->ReturnCode = (int) p1;
  193.                     if (wnd->Modal)
  194.                         PostMessage(wnd, ENDDIALOG, 0, 0);
  195.                     else
  196.                         SendMessage(wnd, CLOSE_WINDOW, TRUE, 0);
  197.                     return TRUE;
  198.                 case ID_HELP:
  199.                     if ((int)p2 != 0)
  200.                         return TRUE;
  201.                     return DisplayHelp(wnd, db->HelpName);
  202.                 default:
  203.                     break;
  204.             }
  205.             break;
  206.         case PAINT:
  207.             p2 = TRUE;
  208.             break;
  209.         case CLOSE_WINDOW:
  210.             if (!p1)    {
  211.                 SendMessage(wnd, COMMAND, ID_CANCEL, 0);
  212.                 return TRUE;
  213.             }
  214.             break;
  215.         default:
  216.             break;
  217.     }
  218.     return BaseWndProc(DIALOG, wnd, msg, p1, p2);
  219. }
  220.  
  221. BOOL DialogBox(WINDOW wnd, DBOX *db, BOOL Modal,
  222.     int (*wndproc)(struct window *, enum messages, PARAM, PARAM))
  223. {
  224.     BOOL rtn;
  225.     int x = db->dwnd.x, y = db->dwnd.y;
  226.     CTLWINDOW *ct;
  227.     WINDOW oldFocus = inFocus;
  228.     WINDOW DialogWnd;
  229.  
  230.     if (!Modal && wnd != NULL)    {
  231.         x += GetLeft(wnd);
  232.         y += GetTop(wnd);
  233.     }
  234.     DialogWnd = CreateWindow(DIALOG,
  235.                         db->dwnd.title,
  236.                         x, y,
  237.                         db->dwnd.h,
  238.                         db->dwnd.w,
  239.                         db,
  240.                         wnd,
  241.                         wndproc,
  242.                         Modal ? SAVESELF : 0);
  243.     DialogWnd->Modal = Modal;
  244.     SendMessage(inFocus, SETFOCUS, FALSE, 0);
  245.     SendMessage(DialogWnd, SHOW_WINDOW, 0, 0);
  246.     SendMessage(((CTLWINDOW *)(DialogWnd->dFocus))->wnd, SETFOCUS, TRUE, 0);
  247.     SendMessage(DialogWnd, INITIATE_DIALOG, 0, 0);
  248.     if (Modal)    {
  249.         SendMessage(DialogWnd, CAPTURE_MOUSE, 0, 0);
  250.         SendMessage(DialogWnd, CAPTURE_KEYBOARD, 0, 0);
  251.         while (dispatch_message())
  252.             ;
  253.         rtn = DialogWnd->ReturnCode == ID_OK;
  254.         SendMessage(DialogWnd, RELEASE_MOUSE, 0, 0);
  255.         SendMessage(DialogWnd, RELEASE_KEYBOARD, 0, 0);
  256.         SendMessage(inFocus, SETFOCUS, FALSE, 0);
  257.         SendMessage(DialogWnd, CLOSE_WINDOW, TRUE, 0);
  258.         SendMessage(oldFocus, SETFOCUS, TRUE, 0);
  259.         if (rtn)    {
  260.             ct = db->ctl;
  261.             while (ct->class)    {
  262.                 ct->wnd = NULL;
  263.                 if (ct->class == RADIOBUTTON || ct->class == CHECKBOX)
  264.                     ct->isetting = ct->setting;
  265.                 ct++;
  266.             }
  267.         }
  268.         return rtn;
  269.     }
  270.     return FALSE;
  271. }
  272.  
  273. static int inFocusCommand(DBOX *db)
  274. {
  275.     CTLWINDOW *ct = db->ctl;
  276.     while (ct->class)    {
  277.         if (ct->wnd == inFocus)
  278.             return ct->command;
  279.         ct++;
  280.     }
  281.     return -1;
  282. }
  283.  
  284. CTLWINDOW *FindCommand(DBOX *db, enum commands cmd, int class)
  285. {
  286.     CTLWINDOW *ct = db->ctl;
  287.     while (ct->class)    {
  288.         if (ct->class == class)
  289.             if (cmd == ct->command)
  290.                 return ct;
  291.         ct++;
  292.     }
  293.     return NULL;
  294. }
  295.  
  296. WINDOW ControlWindow(DBOX *db, enum commands cmd)
  297. {
  298.     CTLWINDOW *ct = db->ctl;
  299.     while (ct->class)    {
  300.         if (ct->class != TEXT && cmd == ct->command)
  301.             return ct->wnd;
  302.         ct++;
  303.     }
  304.     return NULL;
  305. }
  306.  
  307. void PushRadioButton(DBOX *db, enum commands cmd)
  308. {
  309.     CTLWINDOW *ct = FindCommand(db, cmd, RADIOBUTTON);
  310.     if (ct != NULL)    {
  311.         SetRadioButton(db, ct);
  312.         ct->isetting = ON;
  313.     }
  314. }
  315.  
  316. static struct {
  317.     CTLWINDOW *rct;
  318. } rbs[MAXRADIOS];
  319.  
  320. static void SetRadioButton(DBOX *db, CTLWINDOW *ct)
  321. {
  322.     CTLWINDOW *ctt = db->ctl;
  323.     int i;
  324.  
  325.     /* --- clear all the radio buttons
  326.                 in this group on the dialog box --- */
  327.  
  328.     /* -------- build a table of all radio buttons at the
  329.             same x vector ---------- */
  330.     for (i = 0; i < MAXRADIOS; i++)
  331.         rbs[i].rct = NULL;
  332.     while (ctt->class)    {
  333.         if (ctt->class == RADIOBUTTON)
  334.             if (ct->dwnd.x == ctt->dwnd.x)
  335.                 rbs[ctt->dwnd.y].rct = ctt;
  336.         ctt++;
  337.     }
  338.  
  339.     /* ----- find the start of the radiobutton group ---- */
  340.     i = ct->dwnd.y;
  341.     while (i >= 0 && rbs[i].rct != NULL)
  342.         --i;
  343.     /* ---- ignore everthing before the group ------ */
  344.     while (i >= 0)
  345.         rbs[i--].rct = NULL;
  346.  
  347.     /* ----- find the end of the radiobutton group ---- */
  348.     i = ct->dwnd.y;
  349.     while (i < MAXRADIOS && rbs[i].rct != NULL)
  350.         i++;
  351.     /* ---- ignore everthing past the group ------ */
  352.     while (i < MAXRADIOS)
  353.         rbs[i++].rct = NULL;
  354.  
  355.     for (i = 0; i < MAXRADIOS; i++)    {
  356.         if (rbs[i].rct != NULL)    {
  357.             int wason = rbs[i].rct->setting;
  358.             rbs[i].rct->setting = OFF;
  359.             if (wason)
  360.                 SendMessage(rbs[i].rct->wnd, PAINT, 0, 0);
  361.         }
  362.     }
  363.     ct->setting = ON;
  364.     SendMessage(ct->wnd, PAINT, 0, 0);
  365. }
  366.  
  367. BOOL RadioButtonSetting(DBOX *db, enum commands cmd)
  368. {
  369.     CTLWINDOW *ct = FindCommand(db, cmd, RADIOBUTTON);
  370.     if (ct != NULL)
  371.         return (ct->setting == ON);
  372.     return FALSE;
  373. }
  374.  
  375. static void ControlSetting(DBOX *db, enum commands cmd,
  376.                                     int class, int setting)
  377. {
  378.     CTLWINDOW *ct = FindCommand(db, cmd, class);
  379.     if (ct != NULL)
  380.         ct->isetting = setting;
  381. }
  382.  
  383. void SetCheckBox(DBOX *db, enum commands cmd)
  384. {
  385.     ControlSetting(db, cmd, CHECKBOX, ON);
  386. }
  387.  
  388. void ClearCheckBox(DBOX *db, enum commands cmd)
  389. {
  390.     ControlSetting(db, cmd, CHECKBOX, OFF);
  391. }
  392.  
  393. void EnableButton(DBOX *db, enum commands cmd)
  394. {
  395.     ControlSetting(db, cmd, BUTTON, ON);
  396. }
  397.  
  398. void DisableButton(DBOX *db, enum commands cmd)
  399. {
  400.     ControlSetting(db, cmd, BUTTON, OFF);
  401. }
  402.  
  403. BOOL CheckBoxSetting(DBOX *db, enum commands cmd)
  404. {
  405.     CTLWINDOW *ct = FindCommand(db, cmd, CHECKBOX);
  406.     if (ct != NULL)
  407.         return (ct->isetting == ON);
  408.     return FALSE;
  409. }
  410.  
  411. char *GetDlgTextString(DBOX *db, enum commands cmd, CLASS class)
  412. {
  413.     CTLWINDOW *ct = FindCommand(db, cmd, class);
  414.     if (ct != NULL)
  415.         return ct->itext;
  416.     else
  417.         return NULL;
  418. }
  419.  
  420. void SetDlgTextString(DBOX *db, enum commands cmd, char *text, CLASS class)
  421. {
  422.     CTLWINDOW *ct = FindCommand(db, cmd, class);
  423.     if (ct != NULL)    {
  424.         ct->itext = realloc(ct->itext, strlen(text)+1);
  425.         if (ct->itext != NULL)
  426.             strcpy(ct->itext, text);
  427.     }
  428. }
  429.  
  430. void PutComboListText(WINDOW wnd, enum commands cmd, char *text)
  431. {
  432.     CTLWINDOW *ct = FindCommand(wnd->extension, cmd, COMBOBOX);
  433.     if (ct != NULL)        {
  434.         WINDOW lwnd = ((WINDOW)(ct->wnd))->extension;
  435.         SendMessage(lwnd, ADDTEXT, (PARAM) text, 0);
  436.     }
  437. }
  438.  
  439. void PutItemText(WINDOW wnd, enum commands cmd, char *text)
  440. {
  441.     CTLWINDOW *ct = FindCommand(wnd->extension, cmd, EDITBOX);
  442.  
  443.     if (ct == NULL)
  444.         ct = FindCommand(wnd->extension, cmd, TEXTBOX);
  445.     if (ct == NULL)
  446.         ct = FindCommand(wnd->extension, cmd, COMBOBOX);
  447.     if (ct == NULL)
  448.         ct = FindCommand(wnd->extension, cmd, LISTBOX);
  449.     if (ct == NULL)
  450.         ct = FindCommand(wnd->extension, cmd, SPINBUTTON);
  451.     if (ct == NULL)
  452.         ct = FindCommand(wnd->extension, cmd, TEXT);
  453.     if (ct != NULL)        {
  454.         WINDOW cwnd = (WINDOW) (ct->wnd);
  455.         switch (ct->class)    {
  456.             case COMBOBOX:
  457.             case EDITBOX:
  458.                 SendMessage(cwnd, CLEARTEXT, 0, 0);
  459.                 SendMessage(cwnd, ADDTEXT, (PARAM) text, 0);
  460.                 if (!isMultiLine(cwnd))
  461.                     SendMessage(cwnd, PAINT, 0, 0);
  462.                 break;
  463.             case LISTBOX:
  464.             case TEXTBOX:
  465.             case SPINBUTTON:
  466.                 SendMessage(cwnd, ADDTEXT, (PARAM) text, 0);
  467.                 break;
  468.             case TEXT:    {
  469.                 SendMessage(cwnd, CLEARTEXT, 0, 0);
  470.                 SendMessage(cwnd, ADDTEXT, (PARAM) text, 0);
  471.                 SendMessage(cwnd, PAINT, 0, 0);
  472.                 break;
  473.             }
  474.             default:
  475.                 break;
  476.         }
  477.     }
  478. }
  479.  
  480. void GetItemText(WINDOW wnd, enum commands cmd, char *text, int len)
  481. {
  482.     CTLWINDOW *ct = FindCommand(wnd->extension, cmd, EDITBOX);
  483.  
  484.     if (ct == NULL)
  485.         ct = FindCommand(wnd->extension, cmd, COMBOBOX);
  486.     if (ct == NULL)
  487.         ct = FindCommand(wnd->extension, cmd, TEXTBOX);
  488.     if (ct == NULL)
  489.         ct = FindCommand(wnd->extension, cmd, TEXT);
  490.     if (ct != NULL)    {
  491.         WINDOW cwnd = (WINDOW) (ct->wnd);
  492.         if (cwnd != NULL)    {
  493.             switch (ct->class)    {
  494.                 case TEXT:
  495.                     if (GetText(cwnd) != NULL)    {
  496.                         unsigned char *cp = strchr(GetText(cwnd), '\n');
  497.                         if (cp != NULL)
  498.                             len = (int) (cp - GetText(cwnd));
  499.                         strncpy(text, GetText(cwnd), len);
  500.                         *(text+len) = '\0';
  501.                     }
  502.                     break;
  503.                 case TEXTBOX:
  504.                     if (GetText(cwnd) != NULL)
  505.                         strncpy(text, GetText(cwnd), len);
  506.                     break;
  507.                 case COMBOBOX:
  508.                 case EDITBOX:
  509.                     SendMessage(cwnd, GETTEXT, (PARAM) text, len);
  510.                     break;
  511.                 default:
  512.                     break;
  513.             }
  514.         }
  515.     }
  516. }
  517.  
  518. void GetDlgListText(WINDOW wnd, char *text, enum commands cmd)
  519. {
  520.     CTLWINDOW *ct = FindCommand(wnd->extension, cmd, LISTBOX);
  521.     int sel = SendMessage(ct->wnd, LB_CURRENTSELECTION, 0, 0);
  522.     SendMessage(ct->wnd, LB_GETTEXT, (PARAM) text, sel);
  523. }
  524.  
  525. static int dircmp(const void *c1, const void *c2)
  526. {
  527.     return stricmp(*(char **)c1, *(char **)c2);
  528. }
  529.  
  530. BOOL DlgDirList(WINDOW wnd, char *fspec,
  531.                 enum commands nameid, enum commands pathid,
  532.                 unsigned attrib)
  533. {
  534.     int ax, i = 0, criterr = 1;
  535.     struct ffblk ff;
  536.     CTLWINDOW *ct = FindCommand(wnd->extension, nameid, LISTBOX);
  537.     WINDOW lwnd;
  538.     char **dirlist = NULL;
  539.  
  540.     CreatePath(path, fspec, TRUE, TRUE);
  541.  
  542.     if (ct != NULL)    {
  543.         lwnd = ct->wnd;
  544.         SendMessage(ct->wnd, CLEARTEXT, 0, 0);
  545.  
  546.         if (attrib & 0x8000)    {
  547.             union REGS regs;
  548.             char drname[15];
  549.             unsigned int cd, dr;
  550.  
  551.             cd = getdisk();
  552.             for (dr = 0; dr < 26; dr++)    {
  553.                 unsigned ndr;
  554.                 setdisk(dr);
  555.                 ndr = getdisk();
  556.                 if (ndr == dr)    {
  557.                     /* ------- test for remapped B drive ------- */
  558.                     if (dr == 1)    {
  559.                         regs.x.ax = 0x440e;        /* IOCTL function 14 */
  560.                         regs.h.bl = dr+1;
  561.                         int86(DOS, ®s, ®s);
  562.                         if (regs.h.al != 0)
  563.                             continue;
  564.                     }
  565.  
  566.                     sprintf(drname, "[%c:]", dr+'A');
  567.  
  568.                     /* ------ test for network or RAM disk ---- */
  569.                     regs.x.ax = 0x4409;        /* IOCTL function 9 */
  570.                     regs.h.bl = dr+1;
  571.                     int86(DOS, ®s, ®s);
  572.                     if (!regs.x.cflag)    {
  573.                         if (regs.x.dx & 0x1000)
  574.                             strcat(drname, " (Network)");
  575.                         else if (regs.x.dx == 0x0800)
  576.                             strcat(drname, " (RAMdisk)");
  577.                     }
  578.                     SendMessage(lwnd, ADDTEXT, (PARAM) drname, 0);
  579.                 }
  580.             }
  581.             setdisk(cd);
  582.         }
  583.  
  584.         while (criterr == 1)    {
  585.             ax = findfirst(path, &ff, attrib & 0x3f);
  586.             criterr = TestCriticalError();
  587.         }
  588.         if (criterr)
  589.             return FALSE;
  590.         while (ax == 0)    {
  591.             if (!((attrib & 0x4000) &&
  592.                     (ff.ff_attrib & (attrib & 0x3f)) == 0) &&
  593.                         strcmp(ff.ff_name, "."))    {
  594.                 char fname[15];
  595.                 sprintf(fname, (ff.ff_attrib & 0x10) ?
  596.                                 "[%s]" : "%s" , ff.ff_name);
  597.                 dirlist = realloc(dirlist, sizeof(char *)*(i+1));
  598.                 if (dirlist != NULL)    {
  599.                     dirlist[i] = malloc(strlen(fname)+1);
  600.                     if (dirlist[i] != NULL)
  601.                         strcpy(dirlist[i], fname);
  602.                     i++;
  603.                 }
  604.             }
  605.             ax = findnext(&ff);
  606.         }
  607.         if (dirlist != NULL)    {
  608.             int j;
  609.             /* -- sort file/drive/directory list box data -- */
  610.             qsort(dirlist, i, sizeof(void *), dircmp);
  611.  
  612.             /* ---- send sorted list to list box ---- */
  613.             for (j = 0; j < i; j++)    {
  614.                 SendMessage(lwnd, ADDTEXT, (PARAM) dirlist[j], 0);
  615.                 free(dirlist[j]);
  616.             }
  617.             free(dirlist);
  618.         }
  619.         SendMessage(lwnd, SHOW_WINDOW, 0, 0);
  620.     }
  621.  
  622.     if (pathid)    {
  623.         fnmerge(path, drive, dir, NULL, NULL);
  624.         PutItemText(wnd, pathid, path);
  625.     }
  626.  
  627.     return TRUE;
  628. }
  629.  
  630. static CTLWINDOW *AssociatedControl(DBOX *db, enum commands Tcmd)
  631. {
  632.     CTLWINDOW *ct = db->ctl;
  633.     while (ct->class)    {
  634.         if (ct->class != TEXT)
  635.             if (ct->command == Tcmd)
  636.                 break;
  637.         ct++;
  638.     }
  639.     return ct;
  640. }
  641.  
  642. static void dbShortcutKeys(DBOX *db, int ky)
  643. {
  644.     CTLWINDOW *ct;
  645.     int ch = AltConvert(ky);
  646.  
  647.     if (ch != 0)    {
  648.         ct = db->ctl;
  649.         while (ct->class)    {
  650.             char *cp = ct->itext;
  651.             while (cp && *cp)    {
  652.                 if (*cp == SHORTCUTCHAR && tolower(*(cp+1)) == ch)    {
  653.                     if (ct->class == TEXT)
  654.                         ct = AssociatedControl(db, ct->command);
  655.                     if (ct->class == RADIOBUTTON)
  656.                         SetRadioButton(db, ct);
  657.                     else if (ct->class == CHECKBOX)    {
  658.                         ct->setting ^= ON;
  659.                         SendMessage(ct->wnd, PAINT, 0, 0);
  660.                     }
  661.                     else if (ct->class)    {
  662.                         SendMessage(ct->wnd, SETFOCUS, TRUE, 0);
  663.                         if (ct->class == BUTTON)
  664.                             SendMessage(ct->wnd, KEYBOARD, '\r', 0);
  665.                     }
  666.                     return;
  667.                 }
  668.                 cp++;
  669.             }
  670.             ct++;
  671.         }
  672.     }
  673. }
  674.  
  675. void SetScrollBars(WINDOW wnd)
  676. {
  677.     int oldattr = GetAttribute(wnd);
  678.     if (wnd->wlines > ClientHeight(wnd))
  679.         AddAttribute(wnd, VSCROLLBAR);
  680.     else 
  681.         ClearAttribute(wnd, VSCROLLBAR);
  682.     if (wnd->textwidth > ClientWidth(wnd))
  683.         AddAttribute(wnd, HSCROLLBAR);
  684.     else 
  685.         ClearAttribute(wnd, HSCROLLBAR);
  686.     if (GetAttribute(wnd) != oldattr)
  687.         SendMessage(wnd, BORDER, 0, 0);
  688. }
  689.  
  690. /* generic window processor used by all dialog box control windows */
  691. static int ControlProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  692. {
  693.     DBOX *db;
  694.     CTLWINDOW *ct;
  695.  
  696.     if (wnd == NULL)
  697.         return FALSE;
  698.     db = GetParent(wnd) ? GetParent(wnd)->extension : NULL;
  699.     ct = GetControl(wnd);
  700.  
  701.     switch (msg)    {
  702.         case CREATE_WINDOW:
  703.             ct = wnd->ct = wnd->extension;
  704.             wnd->extension = NULL;
  705.             if (ct != NULL)
  706.                 ct->wnd = wnd;
  707.             break;
  708.         case KEYBOARD:
  709.             switch ((int) p1)    {
  710.                 case F1:
  711.                     if (WindowMoving || WindowSizing)
  712.                         break;
  713.                     if (!DisplayHelp(wnd, ct->help))
  714.                         SendMessage(GetParent(wnd), COMMAND, ID_HELP, 0);
  715.                     return TRUE;
  716.                 case ' ':
  717.                     if (!((int)p2 & ALTKEY))
  718.                         break;
  719.                 case ALT_F6:
  720.                 case CTRL_F4:
  721.                 case ALT_F4:
  722.                     PostMessage(GetParent(wnd), msg, p1, p2);
  723.                     return TRUE;
  724.                 default:
  725.                     break;
  726.             }
  727.             if (GetClass(wnd) == EDITBOX)
  728.                 if (isMultiLine(wnd))
  729.                     break;
  730.             switch ((int) p1)    {
  731.                 case UP:
  732.                     if (!isDerivedFrom(wnd, LISTBOX))    {
  733.                         p1 = CTRL_FIVE;
  734.                         p2 = LEFTSHIFT;
  735.                     }
  736.                     break;
  737.                 case BS:
  738.                     if (!isDerivedFrom(wnd, EDITBOX))    {
  739.                         p1 = CTRL_FIVE;
  740.                         p2 = LEFTSHIFT;
  741.                     }
  742.                     break;
  743.                 case DN:
  744.                     if (!isDerivedFrom(wnd, LISTBOX) &&
  745.                             !isDerivedFrom(wnd, COMBOBOX))
  746.                         p1 = '\t';
  747.                     break;
  748.                 case FWD:
  749.                     if (!isDerivedFrom(wnd, EDITBOX))
  750.                         p1 = '\t';
  751.                     break;
  752.                 case '\r':
  753.                     if (isDerivedFrom(wnd, EDITBOX))
  754.                         if (isMultiLine(wnd))
  755.                             break;
  756.                     if (isDerivedFrom(wnd, BUTTON))
  757.                         break;
  758.                     SendMessage(GetParent(wnd), COMMAND, ID_OK, 0);
  759.                     return TRUE;
  760.                 default:
  761.                     break;
  762.             }
  763.             break;
  764.         case PAINT:
  765.             if (GetClass(wnd) == EDITBOX ||
  766.                     GetClass(wnd) == LISTBOX ||
  767.                         GetClass(wnd) == TEXTBOX)
  768.                 SetScrollBars(wnd);
  769.             break;
  770.         case BORDER:
  771.             if (GetClass(wnd) == EDITBOX)    {
  772.                 WINDOW oldFocus = inFocus;
  773.                 inFocus = NULL;
  774.                 DefaultWndProc(wnd, msg, p1, p2);
  775.                 inFocus = oldFocus;
  776.                 return TRUE;
  777.             }
  778.             break;
  779.         case SETFOCUS:
  780.             if (p1)    {
  781.                 DefaultWndProc(wnd, msg, p1, p2);
  782.                 GetParent(wnd)->dFocus = ct;
  783.                 SendMessage(GetParent(wnd), COMMAND,
  784.                     inFocusCommand(db), ENTERFOCUS);
  785.                 return TRUE;
  786.             }
  787.             else 
  788.                 SendMessage(GetParent(wnd), COMMAND,
  789.                     inFocusCommand(db), LEAVEFOCUS);
  790.             break;
  791.         case CLOSE_WINDOW:
  792.             if (ct != NULL)
  793.                 if (GetParent(wnd)->ReturnCode == ID_OK &&
  794.                         (ct->class == EDITBOX || ct->class == COMBOBOX))
  795.                     if (wnd->TextChanged)
  796.                         if ((ct->itext = realloc(ct->itext,    strlen(wnd->text)+1)) != NULL)    {
  797.                             strcpy(ct->itext, wnd->text);
  798.                             if (!isMultiLine(wnd))    {
  799.                                 char *cp = ct->itext+strlen(ct->itext)-1;
  800.                                 if (*cp == '\n')
  801.                                     *cp = '\0';
  802.                             }
  803.                         }
  804.             break;
  805.         default:
  806.             break;
  807.     }
  808.     return DefaultWndProc(wnd, msg, p1, p2);
  809. }
  810.  
  811. /* ----- Create unambiguous path from file spec, filling in the
  812.      drive and directory if incomplete. Optionally change to
  813.      the new drive and subdirectory ------ */
  814. void CreatePath(char *path, char *fspec, int InclName, int Change)
  815. {
  816.     int cm = 0;
  817.     unsigned currdrive;
  818.     char currdir[64];
  819.     char *cp;
  820.  
  821.     if (!Change)    {
  822.         /* ----- save the current drive and subdirectory ----- */
  823.         currdrive = getdisk();
  824.         getcwd(currdir, sizeof currdir);
  825.         memmove(currdir, currdir+2, strlen(currdir+1));
  826.         cp = currdir+strlen(currdir)-1;
  827.         if (*cp == '\\')
  828.             *cp = '\0';
  829.     }
  830.  
  831.     *drive = *dir = *name = *ext = '\0';
  832.     fnsplit(fspec, drive, dir, name, ext);
  833.     if (!InclName)
  834.         *name = *ext = '\0';
  835.     *drive = toupper(*drive);
  836.  
  837.     if (*ext)
  838.         cm |= EXTENSION;
  839.     if (InclName && *name)
  840.         cm |= FILENAME;
  841.     if (*dir)
  842.         cm |= DIRECTORY;
  843.     if (*drive)
  844.         cm |= DRIVE;
  845.  
  846.     if (cm & DRIVE)
  847.         setdisk(*drive - 'A');
  848.     else     {
  849.         *drive = getdisk();
  850.         *drive += 'A';
  851.     }
  852.  
  853.     if (cm & DIRECTORY)    {
  854.         cp = dir+strlen(dir)-1;
  855.         if (*cp == '\\')
  856.             *cp = '\0';
  857.         chdir(dir);
  858.     }
  859.     getcwd(dir, sizeof dir);
  860.     memmove(dir, dir+2, strlen(dir+1));
  861.  
  862.     if (InclName)    {
  863.         if (!(cm & FILENAME))
  864.             strcpy(name, "*");
  865.         if (!(cm & EXTENSION) && strchr(fspec, '.') != NULL)
  866.             strcpy(ext, ".*");
  867.     }
  868.     else
  869.         *name = *ext = '\0';
  870.     if (dir[strlen(dir)-1] != '\\')
  871.         strcat(dir, "\\");
  872.     memset(path, 0, sizeof path);
  873.     fnmerge(path, drive, dir, name, ext);
  874.  
  875.     if (!Change)    {
  876.         setdisk(currdrive);
  877.         chdir(currdir);
  878.     }
  879. }
  880.  
  881. static void ChangeFocus(WINDOW wnd, int direc)
  882. {
  883.     DBOX *db = wnd->extension;
  884.      CTLWINDOW *ct = db->ctl;
  885.      CTLWINDOW *ctt;
  886.  
  887.     /* --- find the control that has the focus --- */
  888.     while (ct->class)    {
  889.         if (ct == wnd->dFocus)
  890.             break;
  891.         ct++;
  892.     }
  893.     if (ct->class)    {
  894.         ctt = ct;
  895.         do    {
  896.             /* ----- point to next or previous control ----- */
  897.             if (direc)    {
  898.                 ct++;
  899.                 if (ct->class == 0)
  900.                     ct = db->ctl;
  901.             }
  902.             else    {
  903.                 if (ct == db->ctl)
  904.                     while (ct->class)
  905.                         ct++;
  906.                 --ct;
  907.             }
  908.  
  909.             if (ct->class != BOX && ct->class != TEXT)    {
  910.                 SendMessage(ct->wnd, SETFOCUS, TRUE, 0);
  911.                 SendMessage(ctt->wnd, PAINT, 0, 0);
  912.                 SendMessage(ct->wnd, PAINT, 0, 0);
  913.                 break;
  914.             }
  915.         } while (ct != ctt);
  916.     }
  917. }
  918.